﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace ASPNETPerformance.App_BusinessLogic.ViewState
{
/// <summary>Moves the hidden __VIEWSTATE form field to the end of the form.</summary>
    public class MoveViewStateFilter : System.IO.MemoryStream
    {
        System.IO.Stream _filter;
        bool _filtered = false;

        /// <param name="filter">A reference to the downstream HttpResponse.Filter.</param>
        public MoveViewStateFilter(System.IO.Stream filter)
        {
            _filter = filter;
        }

        /// <summary>Closes this filter stream.</summary>
        /// <remarks>
        /// The contents of this filter are written to the downstream filter after the hidden
        /// __VIEWSTATE form field is moved.
        /// </remarks>
        public override void Close()
        {
            if (_filtered)
            {
                if (this.Length > 0)
                {
                    byte[] bytes;
                    string content = System.Text.Encoding.UTF8.GetString(this.ToArray());
                    int viewstateStart = content.IndexOf("<input type=\"hidden\" name=\"__VIEWSTATE\"");
                    if (viewstateStart >= 0)
                    {
                        int viewstateEnd = content.IndexOf("/>", viewstateStart) + 2;
                        string viewstate = content.Substring(viewstateStart, viewstateEnd - viewstateStart);
                        content = content.Remove(viewstateStart, viewstateEnd - viewstateStart);
                        int formEndStart = content.IndexOf("</form>");
                        if (formEndStart >= 0)
                            content = content.Insert(formEndStart, viewstate);
                        bytes = System.Text.Encoding.UTF8.GetBytes(content);
                    }
                    else
                    {
                        bytes = this.ToArray();
                    }
                    _filter.Write(bytes, 0, bytes.Length);
                }
                _filter.Close();
            }
            base.Close();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if ((System.Web.HttpContext.Current != null)
              && ("text/html" == System.Web.HttpContext.Current.Response.ContentType))
            {
                base.Write(buffer, offset, count);
                _filtered = true;
            }
            else
            {
                _filter.Write(buffer, offset, count);
                _filtered = false;
            }
        }
    }
}
